
#include "mandelbrot.h"
#include <iostream>

using namespace std;

Mandelbrot::Mandelbrot(int* matriz, int size, int iter){
	this->superficie = matriz;
    this->size = size;
    this->msize = 1<<size;
    this->maxIter = iter;
    this->cota = Float(4);
    this->sizE = Float(msize);
    sizE>>=1;
	p0 = maxIter * 0.11;
	p1 = maxIter * 2/5;
	p2 = maxIter * 3/5;
	p3 = maxIter * 4/5;
	p4 = maxIter * 0.90;
    Complex inicio = Complex(Float(-2), Float(-2));
    Complex fin = Complex(Float(2), Float(2));
    delta = fin.Re();
    delta -= inicio.Re();
    delta >>= size;
    genera(inicio, fin);
}


int Mandelbrot::colorear(int it){
	int valor = 0xFF000000;
	int i = 0;
	int cant = 0;

	unsigned char vr = 0;
	unsigned char vg = 0;
	unsigned char vb = 0;

	float er = 0.0;
	float eg = 0.0;
	float eb = 0.0;

	if(it < p0){
		i = it;

		er = (0x00 - 0x00) / p0;
		vr = 0x00 +i*er;
		eg = (0x00 - 0x00) / p0;
		vg = 0x00 + i*eg;
		eb = (0xff - 0x45) / p0;
		vb = 0xff - i*eb;
		valor +=  vr<<16;
		valor += vg<<8;
		valor += vb;


	} else if ( it < p1){
		cant = p1 - p0;
		i = it - p0;
		er = (0x02 - 0x00) / cant;
		vr = (0x00 + i*er);
		eg = (0x99 - 0x00) / cant;
		vg = (0x00 + i*eg);
		eb = (0x55 - 0x33) / cant;
		vb = 0x55 - i*eb;
		valor +=  vr<<16;
		valor += vg<<8;
		valor += vb;

	} else if (it < p2){
		cant = p2 - p1;
		i = it - p1;
		er = (0xff - 0x02) / cant;
		vr = (0x02 + i*er);
		eg = (0xdd - 0x99) / cant;
		vg = (0x99 + i*eg);
		eb = (0x33 - 0x00) / cant;
		vb = 0x33 - i*eb;
		valor += vr<<16;
		valor += vg<<8;
		valor += vb;


	} else if (it < p3){
		cant = p3 - p2;
		i = it - p2;

		er = (0xff - 0xff) / cant;
		vr = (0xff + i*er);
		eg = (0xdd - 0x22) / cant;
		vg = (0xdd - i*eg);
		eb = (0x22 - 0x00) / cant;
		vb = 0x00 + i*eb;
		valor += vr<<16;
		valor += vg<<8;
		valor += vb;


	} else if (it < p4){
		cant = p4 - p3;
		i = it - p3;

		er = (0xff - 0x88) / cant;
		vr = (0xff - i*er);
		eg = (0x22 - 0x00) / cant;
		vg = (0x22 - i*eg);
		eb = (0x88 - 0x22) / cant;
		vb = 0x00 + i*eb;
		valor += vr<<16;
		valor += vg<<8;
		valor += vb;

	} else if (it < maxIter){

		cant = maxIter - p4;
		i = it - p4;


		er = (0x88 - 0x00) / cant;
		vr = (0x88 - i*er);
		eg = (0x00 - 0x00) / cant;
		vg = (0x00 - i*eg);
		eb = (0x88 - 0x00) / cant;
		vb = 0x88 - i*eb;
		valor += vr<<16;
		valor += vg<<8;
		valor += vb;
	}
	return valor;


}

/** calcula si este punto complejo pertenece o no al conjunto */
int Mandelbrot::calcularPunto(Complex& x){
	Float cero;
	Complex a(cero,cero);

	unsigned int it = 0;
	while(it < maxIter && a.moduloModulo() < cota) {
		a.cuadrado();
   		a.suma(x);
   		it++;
    }
	return it;

}


// dado un centro y un zoom, genera el mandelbrot interno
void Mandelbrot::genera(int x,int y){
	Float auxX(x);
    Float auxY(y);
    maxIter*=1.23; //por que?
    p0 = maxIter * 0.11;
	p1 = maxIter * 0.4;
	p2 = maxIter * 0.6;
	p3 = maxIter * 0.8;
	p4 = maxIter * 0.9;
    Complex centro(posAnterior[0].Re() + delta*auxX,
            posAnterior[0].Im() + delta*auxY);
    delta >>= 1;
    Complex deltaC(delta*sizE, delta*sizE);
    Complex fin = centro + deltaC;
    Complex inicio = centro - deltaC;
	this->genera(inicio, fin);
}

/**
 * Dado un principio un fin genera el mandelbrot para esa region.
 */
void Mandelbrot::genera(const Complex& inicio_arg,const Complex& fin){
	//me guardo la posactual para la próxima
    Complex inicio(inicio_arg);
	posAnterior[0] = inicio;
	posAnterior[1] = fin;
    // delta = ancho ÷ cantidad de pixeles
    Float preRe = inicio.Re();
	int r=0,c;
    int contador = 0;

	while( r < msize) {
        c=0;
		while( c < msize ) {
			/// paralelizar de aca.
			
            int pos = c + r*msize;
			superficie[pos] = colorear(calcularPunto(inicio));
			inicio.setRe( inicio.Re() + delta);
			/// hasta aca
			c++;
            for(; contador <= (pos*80)/(msize*msize); contador++) {
                cout << "|";
            }
		}
        cout.flush();
        r++;
		inicio.setRe(preRe);
		inicio.setIm(inicio.Im() + delta);
	}
    cout << endl;
}
